package cn.keniykey.mc.landterritory.land.api;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import javax.annotation.Nullable;

import org.bukkit.entity.Player;

import cn.keniykey.mc.landterritory.database.AbDataBaseCore;
import cn.keniykey.mc.landterritory.database.DataBaseManager;
import cn.keniykey.mc.landterritory.database.EDataBaseFormEnum;

public final class Land implements Comparable<Land>{
	private final long id; //领地id
	private UUID owner; //领地所有者
	private String name; //领地名字
	private ELandType type; //领地类型
	private HashMap<String,Set<String>> flags; //领地标记
	private LandRange range; //领地范围
	private LandPosition pos; //传送点
	private int level; //领地等级
	private boolean overlap; //重叠
	private int price; //出售价格
	private boolean system; //系统领地
	private String enter; //进入消息
	private String leave; //离开消息
	private boolean deleted = false;
	private boolean builded = false;
	
	public Land(long id,UUID owner,String name,ELandType type,HashMap<String,Set<String>> flags,LandRange range,LandPosition pos,int level,int price,
			boolean overlap,boolean system) {
		this.id = id; this.owner = owner; this.name = name; this.type = type; this.flags = flags; this.range = range; this.pos = pos; 
		this.level = level;this.price = price; this.system = system; this.overlap = overlap;
	}
	private void update(EDataBaseFormEnum label, Object obj) {
		if(this.deleted || !this.builded) return;
		try {
			DataBaseManager.getDataBaseCore().updateLand(this.id, label, obj);
		}catch(Exception ex) {
			ex.printStackTrace();
		}
	}
	public void build() {
		this.builded = true;
	}
	
	public long getID() {
		return this.id;
	}
	public UUID getOwner() {
		return this.owner;
	}
	public void setOwner(UUID owner) {
		if(owner == null || owner.equals(this.owner)) return;
		this.owner = owner;
		this.update(EDataBaseFormEnum.LANDDATA_OWNER, owner);
	}
	public boolean equalsOwner(Land land) {
		return (this.system ? land.system : this.owner.equals(land.owner));
	}
	public boolean equalsOwner(Player player) {
		return (this.system ? LandUtil.hasAdminPer(player, this.getWorldName()) : player.getUniqueId().equals(this.owner));
	}
	public String getName() {
		return this.name;
	}
	public void setName(String name) {
		if(name == null || name.isEmpty() || name.equals(this.name)) return;
		this.name = name;
		this.update(EDataBaseFormEnum.LANDDATA_NAME, name);
	}
	public String getWorldName() {
		return this.range.getWorldName();
	}
	public ELandType getType() {
		return this.type;
	}
	public void setType(ELandType type) {
		if(type == null || !ELandType.TERRITORY.equals(this.type)) return;
		if(ELandType.GROUND.equals(type)) return;
		if(this.type.equals(type)) return;
		this.update(EDataBaseFormEnum.LANDDATA_TYPE, type.getID());
	}
	public HashMap<String,Set<String>> getFlags() {
		return this.flags;
	}
	public void updateFlags() {
		this.update(EDataBaseFormEnum.LANDDATA_FLAGS, AbDataBaseCore.jsonFromFlags(new HashSet<>(this.flags.keySet())));
		final HashMap<String,HashSet<String>> flagpars = new HashMap<>();
		for(final Entry<String, Set<String>> pars : this.flags.entrySet()) {
			if(pars.getValue().isEmpty()) continue;
			flagpars.put(pars.getKey(), new HashSet<>(pars.getValue()));
		} 
		this.update(EDataBaseFormEnum.LANDDATA_PARAMETER, AbDataBaseCore.jsonFromFlagsParameter(flagpars));
	}
	public LandRange getRange() {
		return this.range;
	}
	public long getRangeSize() {
		return this.range.getSize();
	}
	public void setRange(LandRange range) {
		if(this.range == null) return;
		range = range.clone();
		range.fit();
		if(!this.range.equals(range)) this.update(EDataBaseFormEnum.LANDDATA_RANGE, range.toJson());
		this.range = range;
	}
	public LandPosition getPos() {
		return this.pos;
	}
	public void setPos(LandPosition pos) {
		if(this.pos == null || this.pos.equals(pos)) return;
		this.pos = pos.clone();
		this.update(EDataBaseFormEnum.LANDDATA_POS, pos.toJson());
	}
	public int getLevel() {
		return this.level;
	}
	public void setLevel(int level) {
		if(this.level < 1 || this.level == level) return;
		this.level = level;
		this.update(EDataBaseFormEnum.LANDDATA_LEVEL, level);
	}
	public boolean isOverLap() {
		return this.overlap;
	}
	public void setOverLap(boolean overlap) {
		if(this.overlap == overlap) return;
		this.overlap = overlap;
		this.update(EDataBaseFormEnum.LANDDATA_OVERLAP, this.overlap);
	}
	public int getPrice() {
		return this.price;
	}
	public void setPrice(int price) {
		if(price < -1) price = Integer.MAX_VALUE;
		if(this.price == price) return;
		this.price = price;
		this.update(EDataBaseFormEnum.LANDDATA_PRICE, price);
	}
	@Nullable
	public String getEnterMessage() {
		return this.enter;
	}
	public void setEnterMessage(@Nullable String message) {
		if(this.enter == null && message == null) return;
		if(this.enter != null && message != null) {
			if(this.enter.equals(message)) return;
		}
		this.enter = message;
		this.update(EDataBaseFormEnum.LANDMESSAGE_ENTERTIP, message);
	}
	@Nullable
	public String getLeaveMessage() {
		return this.leave;
	}
	public void setLeaveMessage(@Nullable String message) {
		if(this.leave == null && message == null) return;
		if(this.leave != null && message != null) {
			if(this.leave.equals(message)) return;
		}
		this.leave = message;
		this.update(EDataBaseFormEnum.LANDMESSAGE_LEAVETIP, message);
	}
	public boolean isSystem() {
		return this.system;
	}
	public void setSystem(boolean system) {
		if(this.system == system) return;
		this.system = system;
		this.update(EDataBaseFormEnum.LANDDATA_SYSTEM, this.system);
	}
	public boolean isDeleted() {
		return this.deleted;
	}
	public void setDeleted() {
		this.deleted = true;
	}
	
	@Override
	public int hashCode() {
		return (int) this.id;
	}
	@Override
	public boolean equals(Object obj) {
		if (obj == null) return false;
		if (obj == this) return true;
		if (!(obj instanceof Land)) return false;
		final Land land = (Land)obj;
		return (land.getID() == this.id);
	}
	@Override
	public String toString() {
		return this.name;
	}
	@Override
	public int compareTo(Land land) {
		if (land.level != this.level) return (this.level > land.level ? -1 : 1);
		if (this.id == land.id) return 0;
		return (this.id > land.id ? -1 : 1);
	}
}